﻿//
// Created by LiuYou on 2021/4/26.
//

#include <iostream>
#include <unistd.h>
#include <cstring>
#include <cassert>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    std::string serverPort("5004");

    auto serverSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocketFD == -1) {
        assert(serverSocketFD >= 0);
        std::cerr << "socket";
        return -1;
    }

    sockaddr_in serverSockAddrIn{
            .sin_family=AF_INET,
            // 设置端口号, 使用网络字节顺序
            .sin_port=htons(std::stoul(serverPort)),
            {.s_addr=htonl(INADDR_ANY)}
    };

    auto bindServerSocketFD = bind(serverSocketFD, (sockaddr*) &serverSockAddrIn, sizeof(serverSockAddrIn));
    if (bindServerSocketFD != 0) {
        std::cerr << "bind";
        close(serverSocketFD);
        return -1;
    }

    auto listenServerSocketFD = listen(serverSocketFD, 5);
    if (listenServerSocketFD != 0) {
        std::cerr << "listen";
        close(serverSocketFD);
        return -1;
    }

    auto socketAddrInLength = sizeof(sockaddr_in);
    sockaddr_in clientSockAddrIn{};
    // TODO 注意: accept等待到客户端的连接后，创建一个新的socket，函数返回值就是这个新的socket，服务端使用这个新的socket和客户端进行报文的收发。
    auto acceptSocketFD = accept(serverSocketFD, (sockaddr*) &clientSockAddrIn, (socklen_t*) &socketAddrInLength);

    // 接受和发送
    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    char buffer[1024];
    for (;;) {
        std::memset(buffer, 0, sizeof(buffer));
        auto recvRet = recv(acceptSocketFD, buffer, sizeof(buffer), 0);
        if (recvRet <= 0) {
            // TODO 注意: 重要! 如果Client不发送信息后, 即发送完信息后, Client继续运行知道结束。
            //  而Server会执行到此if语句内部, 然后break退出循环, 然后运行结束。
//            std::cerr << "recv" << std::endl;
            std::cout << "recvRet: " << recvRet << std::endl;
            break;
        }
        std::cout << "接受的内容为: " << buffer << std::endl;

        std::memset(buffer, 'c', sizeof(buffer));
//        recvRet = recv(acceptSocketFD, buffer, sizeof(buffer), 0);
//        std::cout << "接受的内容为: " << buffer << std::endl;

        sleep(2);

        // TODO 注意: 这里要注意: 如果Client写了recv函数, 那么Server一定一定一定一定一定要写send函数。
        //  否则: Client的recv函数接受不到信息, 就会一直在等待。

        // TODO 注意: 如果Client没写了recv, 那么Server写send函数可以, 不写也可以。
        //  Server写了send, 这Client如果没写recv函数, 还是可以继续执行Client的(不影响Client继续发送信息)。
        //  Server没写send, 也不会出错。此时就是Client发送, Server接受。然后Client和Server运行结束。
        auto sendRet = send(acceptSocketFD, buffer, strlen(buffer), 0);
        if (sendRet <= 0) {
            std::cerr << "send";
            break;
        }
        std::cout << "Server发送内容为: " << buffer << std::endl;
    }
    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    close(acceptSocketFD);
    close(serverSocketFD);


    return 0;
}